package com.lehecai.core.lottery.fetcher.lotterydraw.impl.worker;

import com.lehecai.core.lottery.LotteryType;
import com.lehecai.core.lottery.fetcher.lotterydraw.LotteryDraw;
import com.lehecai.core.util.CharsetConstant;
import com.lehecai.core.util.CoreDateUtils;
import com.lehecai.core.util.CoreFetcherUtils;
import org.apache.commons.lang.StringUtils;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.HasChildFilter;
import org.htmlparser.filters.StringFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.util.NodeList;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 彩乐乐 开奖结果抓取
 * @author Sunshow
 *
 */
public class LotteryDrawFetchWorkerCailele extends AbstractLotteryDrawFetchWorker {

    private static final Map<LotteryType, String> lotteryTypeMap = new HashMap<LotteryType, String>();
    private static final Map<LotteryType, String> lotteryPhaseConvertionMap = new HashMap<LotteryType, String>();

    private static final String URL_DEFAULT = "http://kjh.cailele.com/history_%s.aspx";
    private static final String URL_HISTORY = "http://kjh.cailele.com/history_%s.aspx?qi=%s";  //phase

    static {
        lotteryTypeMap.put(LotteryType.GDKL10, "klsf");
        lotteryPhaseConvertionMap.put(LotteryType.GDKL10, "-20");

        lotteryTypeMap.put(LotteryType.GXKL10, "gxklsf");

        lotteryTypeMap.put(LotteryType.GD11X5, "gd115");
        lotteryPhaseConvertionMap.put(LotteryType.GD11X5, "20");

        lotteryTypeMap.put(LotteryType.CQ11X5, "cq11x5");
        lotteryPhaseConvertionMap.put(LotteryType.CQ11X5, "20");
    }

	public LotteryDrawFetchWorkerCailele(LotteryType lotteryType){
		super(lotteryType);
	}
	
	@Override
	public LotteryDraw fetchResult(String phase) {
        return this.fetchResultDetail(phase);
    }

	@Override
	public LotteryDraw fetchResultDetail(String phase) {
        LotteryType lotteryType = this.getLotteryType();

        if (StringUtils.isNotBlank(phase) && lotteryPhaseConvertionMap.containsKey(lotteryType)) {
            // 转换彩期
            if (lotteryPhaseConvertionMap.get(lotteryType).startsWith("-")) {
                phase = StringUtils.substringAfter(phase, lotteryPhaseConvertionMap.get(lotteryType).substring(1));
            } else {
                phase = lotteryPhaseConvertionMap.get(lotteryType) + phase;
            }
        }

        String fetchUrl = this.getResultDetailUrl(phase);
        if (StringUtils.isEmpty(fetchUrl)) {
            logger.error("==详细页面==抓取=={}==期号：{}==详细地址不存在，返回null", lotteryType.getName(), phase);
            return null;
        }

        Map<String, String> headerParams = new HashMap<String, String>();
        headerParams.put("Referer", "http://kjh.cailele.com/");
        headerParams.put("user-agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8");

        String data = CoreFetcherUtils.URLGetWithHeaderParams(fetchUrl, headerParams, null, CharsetConstant.CHARSET_GBK);

        if (StringUtils.isEmpty(data)) {
            logger.error("data is null or 404 Not Found, url={}", fetchUrl);
            return null;
        }

        Parser parser;
        try {
            parser = Parser.createParser(data, CharsetConstant.CHARSET_GBK);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            logger.error("解析html出错, data={}", data);
            return null;
        }

        // 找到开奖号码所在的table
        Node drawTableNode = null;
        try {
            NodeFilter drawResultColumnFilter = new StringFilter("中奖号码");
            NodeFilter drawTableHeadFilter = new HasChildFilter(drawResultColumnFilter);
            NodeList nodeList = parser.extractAllNodesThatMatch(drawTableHeadFilter);
            if (nodeList != null && nodeList.size() == 1) {
                drawTableNode = nodeList.elementAt(0).getParent().getParent();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }

        if (drawTableNode == null) {
            logger.error("未找到开奖号码所在的数据区, data={}", data);
            return null;
        }

        // 从table中选择第二行之后开始遍历查找彩期, 如果未指定彩期直接返回第二行
        try {
            parser = Parser.createParser(drawTableNode.toHtml(), CharsetConstant.CHARSET_GBK);
            NodeFilter drawResultRowFilter = new TagNameFilter("TR");
            NodeList nodeList = parser.extractAllNodesThatMatch(drawResultRowFilter);
            if (nodeList == null || nodeList.size() < 2) {
                logger.error("未找到开奖号码区域, data={}", drawTableNode.toHtml());
                return null;
            }
            for (int i = 1; i < nodeList.size(); i++) {
                Node drawRowNode = nodeList.elementAt(i);

                // 第一个td：彩期，第二个td：开奖时间（yyyy-MM-dd HH:mm），第三个td开奖号码
                NodeList drawResultCellList = null;
                try {
                    parser = Parser.createParser(drawRowNode.toHtml(), CharsetConstant.CHARSET_GBK);
                    NodeFilter drawResultCellFilter = new TagNameFilter("TD");
                    drawResultCellList = parser.extractAllNodesThatMatch(drawResultCellFilter);
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                    logger.error("解析开奖结果格式出错, data={}", drawRowNode.toHtml());
                }

                if (drawResultCellList == null || drawResultCellList.size() < 3) {
                    logger.error("开奖结果格式不正确, data={}", drawRowNode.toHtml());
                    continue;
                }

                String fetchedPhase = drawResultCellList.elementAt(0).toPlainTextString();
                if (StringUtils.isBlank(phase) || phase.equals(fetchedPhase)) {
                    // 找到需要抓取的彩期
                    LotteryDraw lotteryDraw = new LotteryDraw();
                    lotteryDraw.setLotteryType(lotteryType);
                    lotteryDraw.setPhase(fetchedPhase);

                    lotteryDraw.setTimeDraw(CoreDateUtils.formatDate(drawResultCellList.elementAt(1).toPlainTextString(), "yyyy-MM-dd HH:mm", CoreDateUtils.DATETIME));

                    NodeList drawResultNumberList = null;
                    try {
                        parser = Parser.createParser(drawResultCellList.elementAt(2).toHtml(), CharsetConstant.CHARSET_GBK);
                        NodeFilter drawResultNumberFilter = new TagNameFilter("DIV");
                        drawResultNumberList = parser.extractAllNodesThatMatch(drawResultNumberFilter);
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                        logger.error("解析开奖结果号码出错, data={}", drawResultCellList.elementAt(2).toHtml());
                    }

                    if (drawResultNumberList == null) {
                        logger.error("解析开奖结果号码格式不正确, data={}", drawResultCellList.elementAt(2).toHtml());
                        return null;
                    }
                    // 遍历开奖号码
                    List<String> drawNumberList = new ArrayList<String>();
                    for (int j = 0; j < drawResultNumberList.size(); j ++) {
                        drawNumberList.add(drawResultNumberList.elementAt(j).toPlainTextString());
                    }
                    lotteryDraw.setResult(StringUtils.join(drawNumberList, ","));

                    if (lotteryPhaseConvertionMap.containsKey(lotteryType)) {
                        // 转换彩期
                        if (lotteryPhaseConvertionMap.get(lotteryType).startsWith("-")) {
                            lotteryDraw.setPhase(lotteryPhaseConvertionMap.get(lotteryType).substring(1) + lotteryDraw.getPhase());
                        } else {
                            lotteryDraw.setPhase(StringUtils.substringAfter(lotteryDraw.getPhase(), lotteryPhaseConvertionMap.get(lotteryType)));
                        }
                    }

                    return lotteryDraw;
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            logger.error("解析数据区格式出错, data={}", drawTableNode.toHtml());
            return null;
        }

        return null;
	}

	@Override
	protected String getResultDetailUrl(String phase) {
        LotteryType lotteryType = this.getLotteryType();

        if (!lotteryTypeMap.containsKey(lotteryType)) {
            return null;
        }

        String lotteryTypeExternal = lotteryTypeMap.get(lotteryType);

        if (StringUtils.isBlank(phase)) {
            return String.format(URL_DEFAULT, lotteryTypeExternal);
        }

        //return String.format(URL_HISTORY, lotteryTypeExternal, phase);
        // 彩乐乐的彩期搜索功能已失效, 都从最新开奖列表中查找
        return String.format(URL_DEFAULT, lotteryTypeExternal);
    }

	@Override
	protected String getResultUrl(String phase) {
		return null;
	}
}
